package com.jnuo.mdb;


import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;

import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;


/**
 * mdb功能包装类
 */
public class NdkWrapper {

    private static final String TAG = "NdkWrapper";

    public static MdbBean getMdbBean() {
        return MdbHelper.INSTANCE.getInstanceMdbBean();
    }

    static {
        System.loadLibrary("mdbLib");
    }

    private static NdkWrapper _instance = null;

    public static NdkWrapper getInstance() {
        if (null == _instance) {
            synchronized (NdkWrapper.class) {
                if (_instance == null) {
                    _instance = new NdkWrapper();
                }
            }
        }
        return _instance;
    }

    private NdkWrapper() {
        mainHandler = new Handler(Looper.getMainLooper());
    }

    //可在mdbInit() 之前 最先调用 (注：不调用不影响使用)
    //目前已有功能，对于纸币器  要以设定不想接收的纸钞面额
    //例如 mdbPreInit("mdb_exclude_amount_bill", "50000.00"); 表示不接收5万面额的纸钞
    public native int mdbPreInit(String key, String val);

    //mdb设备 初始化接口，初始化串口
    //调用一次即可，初始化后，SDK内部会自动初始化MDB设备，自动检测断线重连（刷卡器除外先），自反馈收入金额等
    public native int mdbInit();

    public native void mdbFini();

    public native int mdbIsRunning();

    //异步获取数据，调用mdbAction后，mdbCallback回调会响应相应数据
    //其中mdbCallback参数 type 为 mdb_action表示响应 mdbAction方法；
    //mdbCallback参数 key 为 与 mdbAction方法中的 key 参数一样；
    //mdbCallback参数 buf 等为 获取到的数据
    public native void mdbAction(String key);


    private final Handler mainHandler;
    private MdbCallback mdbCallback = null;
    private volatile MdbType payMdbType = null;//正在支付的现金类型
    private Method printOrderMethod = null;
    private Method printMdbMethod = null;
    private volatile long lastStuckTime = 0;//最后执行卡币退款的时间
    private volatile boolean dispenseCoinning = false;//硬币退币中
    private volatile int bindType = -1;//不能重复绑定或者重复解绑操作,如果重复绑定,会导致之前的订单实际已退钱,但是订单数据还在

    ///谁监听,通知谁的原则
    public void setMdbCallback(MdbCallback mdbCallback) {
        this.mdbCallback = mdbCallback;
    }

    public boolean isBind() {
        return bindType != -1;
    }

    public boolean isDispenseCoinning() {
        return dispenseCoinning;
    }

    private boolean isPaying() {
        return payMdbType != null;
    }

    private void setPayMdbType(MdbType mdbType) {
        payMdbType = mdbType;
    }

    ///当前绑定动作
    public int getBindType() {
        return bindType;
    }

    /**
     * 绑定MDB功能
     *
     * @param bindType 0:仅MDB现金 1:仅MDB刷卡 2:MDB现金和MDB刷卡
     * @return
     */
    public int bindMDB(int bindType) {
        this.bindType = bindType;
        logOrder(String.format("bindMDB:" + bindType));
        setPayMdbType(null);

        boolean mdb_set_enable_bill = (bindType == 0 || bindType == 2);
        boolean mdb_set_enable_coin = (bindType == 0 || bindType == 2);
        boolean mdb_set_enable_cashless = (bindType == 1 || bindType == 2);

        if (mdb_set_enable_bill) {
            mdb_set_enable_bill = MdbParamsHelper.getMdb_set_enable_bill();
        }
        if (mdb_set_enable_coin) {
            mdb_set_enable_coin = MdbParamsHelper.getMdb_set_enable_coin();
        }

        mdbPreInit("mdb_set_enable_bill", mdb_set_enable_bill ? "1" : "0");  // 启动纸币器
        mdbPreInit("mdb_set_enable_coin", mdb_set_enable_coin ? "1" : "0");  // 启动硬币器
        mdbPreInit("mdb_set_enable_cashless", mdb_set_enable_cashless ? "1" : "0");//启用刷卡

//        printLog("启动纸币器:" + mdb_set_enable_bill);
//        printLog("启动硬币器:" + mdb_set_enable_coin);
//        printLog("启用刷卡:" + mdb_set_enable_cashless);

        updateRejectAmount();

        //单次订单金额的最大总金额数
        String mdb_set_cash_off_over_max_amount = MdbParamsHelper.getMdb_set_cash_off_over_max_amount();
        if (!TextUtils.isEmpty(mdb_set_cash_off_over_max_amount)) {//不设置就按so库中的默认值
            mdbPreInit("mdb_set_cash_off_over_max_amount", mdb_set_cash_off_over_max_amount);
        } else {
            mdbPreInit("mdb_set_cash_off_over_max_amount", "0.00");
        }
//        printLog("单次订单金额的最大总金额数:" + mdb_set_cash_off_over_max_amount);


        boolean mdb_save_balance = MdbParamsHelper.getMdb_save_balance();
        //表示是否启动支持掉电余额记忆功能，默认支持
        mdbPreInit("mdb_save_balance", mdb_save_balance ? "1" : "0");
//        printLog("启动存储运行时数据功能:" + mdb_save_balance);

        //表示是否启用纸币器 ESCROW 暂存退钞功能，默认不启用
        String mdb_set_escrow_bill = "0";
        if (mdb_set_enable_bill) {
            String mdb_set_escrow_bill1 = MdbParamsHelper.getMdb_set_escrow_bill();
            printLog("mdb_set_escrow_bill1:" + mdb_set_escrow_bill1);
            mdb_set_escrow_bill = mdb_set_escrow_bill1;
        }
        mdbPreInit("mdb_set_escrow_bill", mdb_set_escrow_bill);  // 在启用纸币器后，启用纸币器 ESCROW 暂存和退钞功能
//        printLog("启用纸币器 ESCROW 暂存退钞功能:" + mdb_set_escrow_bill);

        //表示刷卡机设置是否always_idle模式，默认不设置
        String mdb_set_always_idle_cashless = "0";
        if (mdb_set_enable_cashless) {
            mdb_set_always_idle_cashless = MdbParamsHelper.getMdb_set_always_idle_cashless();
        }
        mdbPreInit("mdb_set_always_idle_cashless", mdb_set_always_idle_cashless);
//        printLog("刷卡机设置是否always_idle模式:" + mdb_set_always_idle_cashless);

        //有些MDB刷卡机支持 该参数 为0，  有些刷卡机支持该参数 为1 有机会再测试非 always idle模式的刷卡机 适配NAYAX 刷卡机
        //表示刷卡机设置请求支付时是否使用,金额扩展数据格式，默认不启用，设置 0 表示不启用，设置 1 表示启用该模式
        String mdb_set_expand_currency_mode_cashless = "0";
        if (mdb_set_enable_cashless) {
            mdb_set_expand_currency_mode_cashless = MdbParamsHelper.getMdb_set_expand_currency_mode_cashless();
        }
        mdbPreInit("mdb_set_expand_currency_mode_cashless", mdb_set_expand_currency_mode_cashless);
//        printLog("刷卡机设置请求支付时是否使用,金额扩展数据格式:" + mdb_set_expand_currency_mode_cashless);

        /*
        表示针对现金订单是否手动退款模式，默认不启用，
        设置 0 表示多出余额自动退款，设置 1 表示多出余额手动退款
         */
        boolean mdb_set_manual_refund = false;
        if (mdb_set_enable_bill || mdb_set_enable_coin) {
            mdb_set_manual_refund = MdbParamsHelper.getMdb_set_manual_refund();
        }
        mdbPreInit("mdb_set_manual_refund", mdb_set_manual_refund ? "1" : "0");
//        printLog("现金订单是否手动退款模式:" + mdb_set_manual_refund);

//        if (bindType == 0 || bindType == 2) {
//            mdbPreInit("mdb_set_dispense_greedily", "1");//在启用纸币器后,启用尽量找零
//        }

//        if (bindType == 1 || bindType == 2) {
//            mdbPreInit("mdb_useamount_dispense_record", "");
//
//        }

        //预设硬币器面额管道低数量位
        boolean mdb_set_enable_tube = MdbParamsHelper.getMdb_set_enable_tube();
        String mdb_set_tube_count_coin_json = MdbParamsHelper.getMdb_set_tube_count_coin();
        if (mdb_set_enable_tube && mdb_set_tube_count_coin_json != null) {
            mdbPreInit("mdb_set_tube_count_coin", mdb_set_tube_count_coin_json);//管道预警
        } else {
            mdbPreInit("mdb_set_tube_count_coin", "");
        }

        //预检查现金找零
        mdbPreInit("mdb_set_prechk_refund", "0");
        //现金找零不足时拒收纸币
        boolean mdb_set_bill_off_on_low_coin = MdbParamsHelper.getMdb_set_bill_off_on_low_coin();
        if (!mdb_set_enable_tube) {//不启用管道预警
            mdb_set_bill_off_on_low_coin = false;
        }
        mdbPreInit("mdb_set_bill_off_on_low_coin", mdb_set_bill_off_on_low_coin ? "1" : "0");

        return mdbInit();
    }

    ///更新当前可以接受的币值
    public void updateRejectAmount() {
        mdbPreInit("mdb_reset_amount_bill", "");  // 重置接收所有面值
        DecimalFormat df = MdbNumUtil.getInstant();
        df.applyPattern("#.00");
        ArrayList<Double> rejectList = MdbParamsHelper.getMdb_exclude_from_next_amount_bill();
        Log.i(TAG, "bill，rejectList:" + rejectList);
        for (Double rejectDouble : rejectList) {
            String format = df.format(rejectDouble);
            logOrder(String.format("updateRejectAmount;拒绝接收的纸币面值:%s", format));
            mdbPreInit("mdb_exclude_from_next_amount_bill", format);  // 拒绝接收的纸币面值
        }

        mdbPreInit("mdb_reset_amount_coin", "");  // 重置接收所有面值
        rejectList = MdbParamsHelper.getMdb_exclude_from_next_amount_coin();
        Log.i(TAG, "coin，rejectList:" + rejectList);
        for (Double rejectDouble : rejectList) {
            String format = df.format(rejectDouble);
            logOrder(String.format("updateRejectAmount;拒绝接收的硬币面值:%s", format));
            mdbPreInit("mdb_exclude_from_next_amount_coin", format);  // 拒绝接收的纸币面值
        }
    }

    // 解绑MDB功能
    public void unBindMDB() {
        bindType = -1;
        setPayMdbType(null);
        mdbFini();
        logOrder(String.format("解绑MDB"));
    }

    // 下单支付
    public void payOrder(MdbType mdbType, double amount, int timeout) {
        payOrder(mdbType, amount, timeout, 0);
    }

    // 下单支付
    public void payOrder(MdbType mdbType, double amount, int timeout, int pid) {
        logOrder("MDB支付开始↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ");
        logOrder("MDB支付开始↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓  ");
        setPayMdbType(mdbType);
        MdbCmdType cmdType = MdbCmdType.PayOrder;
        DecimalFormat df = MdbNumUtil.getInstant("#.00");
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        cmdMap.put("type", mdbType.name());
        cmdMap.put("amount", String.valueOf(df.format(amount)));
        cmdMap.put("timeout", String.valueOf(timeout));
        cmdMap.put("pid", String.valueOf(pid));
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder(String.format("下单支付金额:%s", comJson));
    }

    // 取消订单,会进行自动退钱,并告知设备该订单失败并且结束该订单
    public void cancelOrder(MdbType mdbType) {
        onlyCancelOrder(mdbType);
        finishOrder(mdbType, false);
    }

    ///仅取消订单
    public void onlyCancelOrder(MdbType mdbType) {
        MdbCmdType cmdType = MdbCmdType.CancelOrder;
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        cmdMap.put("type", mdbType.name());
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder(String.format("取消订单指令:%s", comJson));
    }

    ///告知设备该订单成功并且结束该订单
    public void finishSuccessOrder(MdbType mdbType) {
        finishOrder(mdbType, true);
    }

    /**
     * @param isSuccess 通知mdb设备订单结束,并告知订单是否成功,并不会退款
     */
    public void finishOrder(MdbType mdbType, boolean isSuccess) {
        setPayMdbType(null);
        MdbCmdType cmdType = MdbCmdType.FinishOrder;
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        cmdMap.put("type", mdbType.name());
        cmdMap.put("result", isSuccess ? "vend_success" : "vend_failure");
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder(String.format("订单完成或取消后，终结上次订单指令:%s", comJson));


    }

    // 直接退钞
    public void refundAmount(double amount, boolean isCoin) {
        MdbCmdType cmdType = isCoin ? MdbCmdType.RefundAmountCoin : MdbCmdType.RefundAmountBill;
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        cmdMap.put("amount", String.valueOf(amount));
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder(String.format("直接退钞:%s", comJson));
    }


    ///卡币退款
    public void stuckAmount() {

        long time = System.currentTimeMillis();
        if ((time - lastStuckTime) < 5 * 1000) {
            logOrder("5秒内只能执行一次卡币退款");
            return;
        }
        lastStuckTime = time;
        new Thread() {
            @Override
            public void run() {
                SystemClock.sleep(4000);
                getMdbBalanceAction();
            }
        }.start();

        MdbCmdType cmdType = MdbCmdType.StuckAmount;
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder(String.format("卡币退款:%s", comJson));

        cancelOrder(MdbType.cashes);
    }

    public void delayGetMdbBalanceAction() {
        new Thread() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
                getMdbBalanceAction();
            }
        }.start();
    }

    ///查詢上一笔订单结束后余额
    public void getMdbBalanceAction() {
        MdbCmdType cmdType = MdbCmdType.GetTopOrderBalance;
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder(String.format("查询余额:%s", comJson));
        hasEmptyCoinChannelAction();
    }

    ///查询硬币器管道是否有空管道
    private void hasEmptyCoinChannelAction() {
        MdbCmdType cmdType = MdbCmdType.GetHasEmptyCoinChannel;
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder(String.format("查询硬币器管道是否有空管道:%s", comJson));
    }

    public void mdb_order_prechk_continue() {
        MdbCmdType cmdType = MdbCmdType.mdb_order_prechk_continue;
        LinkedHashMap<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("cmd", cmdType.getCmd());
        String comJson = MdbUtil.anyToJson(cmdMap);
        mdbAction(comJson);
        logOrder("找零不足时订单继续");
    }

    public static void mdbCbJsonS(String cmd, byte[] buf) {
        getInstance().mdbCbJsonSNonStatic(cmd, buf);
    }


    /**
     * 非静态方法
     *
     * @param cmd 回调动作 该指令和buf中的json中的cmd指令不同
     * @param buf 详细json数据
     */
    private void mdbCbJsonSNonStatic(String cmd, byte[] buf) {
        String jsonStr = new String(buf, StandardCharsets.UTF_8);
        String print = String.format("mdbCbJsonS cmd = %s , jsonStr = %s", cmd, jsonStr);

        String cmdDesc = "忽略指令";
        for (MdbCmdType value : MdbCmdType.values()) {
            if (TextUtils.equals(value.getCmd(), cmd)) {
                cmdDesc = value.getDesc();
                break;
            }
        }
        logOrder(String.format("(%s)现金设备回调内容:%s", cmdDesc, print));

        //只识别当前定义的指令
        MdbCmdType currentCmdType = null;
        for (MdbCmdType value : MdbCmdType.values()) {
            if (TextUtils.equals(value.getCmd(), cmd)) {
                currentCmdType = value;
                break;
            }
        }
        if (currentCmdType == null) {//只识别当前定义的指令
            return;
        }

        switch (currentCmdType) {
            case mdbPreInit: //预初始动作，所以不予理会
            case mdbAction: //mdb动作仅仅是告知刚才主动下发的指令，所以不予理会
                return;
            case mdb_poll_cashless://mdb刷卡
                break;
            case mdb_sdk_version://mdb当前版本
                MdbHelper.INSTANCE.setMdbVersion(jsonStr);
                break;
            case mdb_state_all://设置硬币器/纸币器状态
                MdbHelper.INSTANCE.setMdbStatus(jsonStr);
                break;
            case mdb_coin_setup://获取硬币器中的信息
                MdbHelper.INSTANCE.setCoinInfo(jsonStr);
                break;
            case mdb_coin_expan://设置硬币器版本
                MdbHelper.INSTANCE.setCoinVersion(jsonStr);
                break;
            case mdb_status_coin://设置硬币器中余额
                MdbHelper.INSTANCE.setCoinBalance(jsonStr);
                break;
            case mdb_bill_setup://获取纸币器中的信息
                MdbHelper.INSTANCE.setBillInfo(jsonStr);
                printLog(String.format("纸币器是否支持退钞功能：%b", (getMdbBean().getZ11Escrow() == 255)));
                break;
            case mdb_bill_expan://设置纸币器版本
                MdbHelper.INSTANCE.setBillVersion(jsonStr);
                break;
        }

        actionCallJson(currentCmdType, cmd, jsonStr);

        if (mdbCallback != null) {
            mainHandler.post(() -> {
                if (mdbCallback != null) {
                    mdbCallback.onMdbInfo();
                }
            });
        }
    }

    ///主动触发命令操作的回调
    private void actionCallJson(MdbCmdType mdbCmdType, String cmd, String jsonStr) {
        HashMap<String, Object> jsonMap = null;
        try {
            Type type = new TypeToken<HashMap<String, Object>>() {
            }.getType();
            jsonMap = MdbUtil.jsonToAny(jsonStr, type);
        } catch (Exception e) {
            e.printStackTrace();
        }
        switch (mdbCmdType) {
            case GetBillDetail://查询零钱
                break;
            case PayOrder: {//下单支付
                //mdbCbJsonS cmd = mdb_order , jsonStr = {"cmd":"mdb_order","result":"err","detail":"un_finished"}
                MdbPayOrderBean orderBean = MdbUtil.jsonToAny(jsonStr, MdbPayOrderBean.class);
                if (isPaying()) {
                    if (orderBean.isOk()) {//下单支付指令成功
                        printLog(mdbCmdType.getDesc() + " : " + orderBean.getOkDesc());
                        if (TextUtils.equals("start", orderBean.getDetail())) {//支付开始
                            if (payMdbType == MdbType.cashes) {
                                cashStart();
                            } else {
                            }

                        } else if (TextUtils.equals("end", orderBean.getDetail())) {//支付结束
                            if (payMdbType == MdbType.cashes) {
                                cashSuccess();
                            } else {
                                onCashless(true, null);
                            }
                        }

                    } else {//下单支付指令失败
                        printLog(mdbCmdType.getDesc() + "失败 : " + orderBean.getErrDesc());
                        String err_detail = orderBean.getDetail();
                        if (payMdbType == MdbType.cashes) {
                            cashFail(err_detail);
                        } else {
                            //{"cmd":"mdb_order","result":"err","err_detail":"vend_denied","amount_order":"0.01","amount_deposited":"0.00"}
                            onCashless(false, err_detail);
                        }
                    }
                }

            }
            break;
            case mdb_poll_coin:
            case mdb_poll_bill://{"cmd":"mdb_poll_bill","state":"ok","detail":"Validator Disabled"}
                if (isPaying()) {
                    if (payMdbType == MdbType.cashes) {
                        MdbStateBean mdbStateBean = MdbUtil.jsonToAny(jsonStr, MdbStateBean.class);
                        if (mdbStateBean != null) {
                            if (mdbStateBean.stateError()) {//设备故障
                                cashFail(mdbStateBean.getDetail());
                            } else {
                                if (TextUtils.equals(mdbStateBean.getDetail(), "Validator Disabled")) {
                                    printLog("拒绝接收纸币");
                                }
                            }
                        }
                    }
                }
                break;
            case mdb_deposited_coin:
            case mdb_deposited_bill: {//支付过程中
                //mdbCbJsonS cmd = mdb_deposited_bill , jsonStr = {"cmd":"mdb_deposited_bill","result":"ok","flag_coin":-1,
                // "vend_deposited":0,"vend_token":0,"amount_deposited":"100.00","amount_total":"100.00","amount_escrow":"no","amount_recycler":"0.0"}
                MdbReceiveAmountBean amountBean = MdbUtil.jsonToAny(jsonStr, MdbReceiveAmountBean.class);
                if (amountBean.isOk()) {
                    double totalAmount = amountBean.totaldAmount();
                    logOrder(String.format("当前收到%s,金额:%.2f,共收到金额:%.2f", amountBean.amountTypeText(), amountBean.depositedAmount(), amountBean.totaldAmount()));
                    cashPaid(totalAmount);
                    getInstance().getMdbBalanceAction();
                }
            }
            break;
            case mdb_over_cancel: {//支付金额超过订单金额,自动找零
                MdbOverCancelBean amountBean = MdbUtil.jsonToAny(jsonStr, MdbOverCancelBean.class);
                if (amountBean.isOk()) {
                    printLog(amountBean.print());
                }
            }
            break;
            case CancelOrder://取消订单
                //mdbCbJsonS cmd = mdb_order_cancel , jsonStr = {"cmd":"mdb_order_cancel","result":"ok","detail":"none_deposited"}
                break;
            case FinishOrder://订单结束
                //mdbCbJsonS cmd = mdb_order_finish , jsonStr = {"cmd":"mdb_order_finish","result":"ok","amount_deposited":"0.0","amount_left":"0.0","vend_token":0}
                if (isPaying()) {
                    if (payMdbType == MdbType.cashless) {//MDB刷卡
//                        CashlessPayOrderBean cashlessPayOrderBean = MdbUtil.jsonToAny(jsonStr, CashlessPayOrderBean.class);
//                        if (cashlessPayOrderBean.isResultOk()) {
//                            onCashless(true, null);
//                            logOrder("当前MDB刷卡成功");
//                        } else {
//                            onCashless(false, cashlessPayOrderBean.getDetail());
//                            logOrder("当前MDB刷卡失败");
//                        }
                    } else {
                        getInstance().delayGetMdbBalanceAction();
                    }
                }
                break;
            case StuckAmount://卡币退款
                break;
            case GetTopOrderBalance: {//上一笔订单结束后余额
                MdbHelper.INSTANCE.setTopOrderBalance(jsonStr);
                if (mdbCallback != null) {
                    mainHandler.post(() -> {
                        if (mdbCallback != null) {
                            mdbCallback.onCashBalancEvent();
                        }
                    });
                }
            }
            break;
            case GetHasEmptyCoinChannel://查询硬币器管道是否有空管道
                MdbHelper.INSTANCE.setHasEmptyCoinChannel(jsonStr);
                break;
            case RefundAmountBill://退钞
            case RefundAmountCoin://退币
                if (jsonMap != null) {
                    //{"cmd":"mdb_dispense_coin","result":"ok","detail":"start","amount_want":"10.00"}
                    if (jsonMap.containsKey("detail")) {
                        String detail = jsonMap.get("detail") + "";
                        if (TextUtils.equals("end_incomplete", detail) ||
                                TextUtils.equals("end_ok", detail)) {
                            dispenseCoinning = false;
                        } else {
                            dispenseCoinning = true;
                        }
                    }
                }
                break;
        }
    }


    /**
     * 过时的回调,不能删除,否则闪退
     *
     * @param cmd
     * @param key
     * @param buf
     * @param buf2
     * @param buf3
     */
    @Deprecated
    public static void mdbCallbackS(String cmd, String key, byte[] buf, byte[] buf2, byte[] buf3) {

    }

    public static void mdbCbLogS(int logPriority, byte[] buf) {
        String jsonStr = new String(buf, StandardCharsets.UTF_8);
        String print = String.format("mdbCbLogS logPriority = %d , jsonStr = %s", logPriority, jsonStr);
        getInstance().logMdb(print);

        //转发记录 到  日志文件，待实现
        //建议做成后台界面配置成， 1  忽略mdb_jni日志存储  2  存储mdb_jni日志到 日志文件  3 存储到其它地方（看是否必要）
    }

    private void cashStart() {
        if (mdbCallback != null) {
            mainHandler.post(() -> {
                if (mdbCallback != null) {
                    mdbCallback.onCashStart();
                }
            });
        }
    }

    private void cashPaid(double progressAmount) {
        if (mdbCallback != null) {
            mainHandler.post(() -> {
                if (mdbCallback != null) {
                    mdbCallback.onCashProgress(progressAmount);
                }
            });
        }
    }

    private void cashSuccess() {
        if (mdbCallback != null) {
            mainHandler.post(() -> {
                if (mdbCallback != null) {
                    mdbCallback.onCashSuccess();
                }
            });
        }
    }

    private void cashFail(String failReason) {

//        getInstance().cancelOrder(MdbType.cashes);//注释该行代码，由调用者结束订单。防止重复下发指令
        //只要订单失败,都会结束该订单
        if (mdbCallback != null) {
            mainHandler.post(() -> {
                if (mdbCallback != null) {
                    mdbCallback.onCashFail(failReason);
                }
            });
        }
    }

    /**
     * MDB刷卡
     *
     * @param success
     * @param failReason
     */
    private void onCashless(final boolean success, final String failReason) {
        if (mdbCallback != null) {
            mainHandler.post(() -> {
                if (mdbCallback != null) {
                    mdbCallback.onCashless(success, failReason);
                }
            });
        }
        if (!success) {
            getInstance().cancelOrder(MdbType.cashless);
        }
    }

    private static void printLog(String msg) {
        Log.i(TAG, msg);
    }


    protected void logOrder(String msg) {

        try {
            if (printOrderMethod == null) {
                String className = "com.jetinno.common.Log4jUtils";
                Class<?> aClass = Class.forName(className);
                printOrderMethod = aClass.getMethod("logOrder", new Class[]{String.class, String.class});
            }
            if (printOrderMethod != null) {
                String tag = TAG;
                String printToText = "order" + " " + msg;
                printOrderMethod.invoke(null, new Object[]{tag, printToText});
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    protected void logMdb(String msg) {
        try {
            if (printMdbMethod == null) {
                String className = "com.jetinno.common.Log4jUtils";
                Class<?> aClass = Class.forName(className);
                printMdbMethod = aClass.getMethod("logMdb", new Class[]{String.class, String.class});
            }
            if (printMdbMethod != null) {
                String tag = TAG;
                String printToText = "mdb" + " " + msg;
                printMdbMethod.invoke(null, new Object[]{tag, printToText});
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}